package checkers3d.logic;

import checkers3d.*;
import java.util.*;
import checkers3d.storage.*;

/**Brenton Dong
 *
 * All other classes should consult this class before PlayingSurfacePosition
 * 
 */
public class PlayingSurface3D {
    
    private PlayingSurfacePosition[][][] surface;//This is the 3D array of Board Positions
    private int x;
    private int y;
    private int z;

    public PlayingSurface3D(int tempx, int tempy, int tempz) {

        //RA: Note that for getSurface2D we need z to be the first axis. Thus,
        //we must internally store the like [z][x][y] instead of [x][y][z]. It
        //should only effect the methods in this class but it is still very
        //confusing.

        z = tempz;
        x = tempx;
        y = tempy;
        surface = new PlayingSurfacePosition[tempz][tempx][tempy];
        for (int k=0; k<tempz; k++){
            for(int i=0; i<tempx; i++){
                for (int j=0; j<tempy; j++){
                    surface[k][i][j] = new PlayingSurfacePosition();
                }
            }
        }
    }

    //This retreives the linked list of Board Objects from a specified position on the board.
    public PlayingSurfacePosition getPosition(Point3D point){
        return surface[point.z][point.x][point.y];
    }

    public LinkedList<IBoardObject> getPositionObjects(Point3D point){
        return surface[point.z][point.x][point.y].getPositionObjects();
    }

    public IBoardObject getPositionDynamicObject(Point3D point){
        for(IBoardObject object : surface[point.z][point.x][point.y].getPositionObjects()){
            if(object instanceof IBoardObjectDynamic){
                return object;
            }
        }
        return null;
    }

    //this returns the amount of Dynamic Pieces on the board belonging to a passed player.
    public int getSurfaceDynamicsAmount(Player player){
        int amount = 0;
        for (int k=0; k<z; k++){
            for(int i=0; i<x; i++){
                for (int j=0; j<y; j++){
                    IBoardObject temp = getPositionDynamicObject(new Point3D(i,j,k));
                    if(temp != null && temp.getOwner() == player)
                        amount++;
                }
            }
        }
        return amount;
    }

    //This allows you to add a Board Object to any position on the board.
    public void addObject(IBoardObject boardObject, Point3D point){
        surface[point.z][point.x][point.y].addObject(boardObject);
    }

    //This allows you to retreive the Overlay status of a Position (square)
    public PlayingSurfacePositionOverlay getOverlay(Point3D point){
        return getPosition(point).getOverlay();
    }

    //This allows you to change the overlay status of a board position
    public void setOverlay(PlayingSurfacePositionOverlay status, Point3D point){
        surface[point.z][point.x][point.y].setOverlay(status);
    }

    //This flips the board both vertically and horizontally (turning around)
    public void flip(){
        int i = 0;
        int iTemp = x-1;
        int iCount = 0;
        int j = 0;
        int jTemp = y-1;
        int jCount = 0;
        PlayingSurfacePosition[][][] tempSurface = new PlayingSurfacePosition[z][x][y];
        for(int k=0; k<z; k++){
            for(jCount = 0; jCount < y; jCount++){
                iTemp = x-1;
                i = 0;
                while(i < x){
                    tempSurface[k][i][jCount] = surface[k][iTemp][jCount];
                    i++;
                    iTemp--;
                }
            }
            for(iCount = 0; iCount < x; iCount++){
                jTemp = y-1;
                j = 0;
                while(j < y){
                    surface[k][iCount][j] = tempSurface[k][iCount][jTemp];
                    j++;
                    jTemp--;
                }
            }
        }
    }

    //returns whether or not any position of the surface is FORCED_SELECTED
    public boolean isForced(){
        for (int k=0; k<z; k++){
            for(int i=0; i<x; i++){
                for (int j=0; j<y; j++){
                    if(surface[k][i][j].getOverlay() == PlayingSurfacePositionOverlay.FORCED_SELECTED)
                        return true;
                }
            }
        }
        return false;
    }

    public PlayingSurfacePosition[][] getSurface2D(int z)
    {
        return surface[z];
    }

    public int getSizeX()
    {
        return x;
    }

    public int getSizeY()
    {
        return y;
    }

    public int getSizeZ()
    {
        return z;
    }

    @Override
    public PlayingSurface3D clone()
    {
        PlayingSurface3D clone = new PlayingSurface3D(getSizeX(), getSizeY(), getSizeZ());

        for(int x = 0; x < getSizeX(); x++)
            for(int y = 0; y < getSizeY(); y++)
                for(int z = 0; z < getSizeZ(); z++)
                {
                    Point3D target = new Point3D(x, y, z);

                    for(IBoardObject object : getPosition(target).getPositionObjects())
                        clone.getPositionObjects(target).add(object.clone());

                    clone.setOverlay(this.getOverlay(target), target);
                }

        return clone;
    }
}
